/** @file

Copyright (c) 2006-2023, Kunlun BIOS, Kunlun Technology (Beijing) Co., Ltd.. All
Rights Reserved.

You may not reproduce, distribute, publish, display, perform, modify, adapt,
transmit, broadcast, present, recite, release, license or otherwise exploit
any part of this publication in any form, by any means, without the prior
written permission of Kunlun Technology (Beijing) Co., Ltd..

**/


#ifndef KL_S3_RESUME_UNLOCK_HDD_PEI_LIB_H_
#define KL_S3_RESUME_UNLOCK_HDD_PEI_LIB_H_


#define S3_UNLOCK_HDD_MEM_BASE_VARIABLE       L"S3UnlockHddMemBaseVar"
#define PCI_BRIDGE_CLASS_BASE_OFFSET          0x0B
#define PCI_BRIDGE_CLASS_SUB_OFFSET           0x0A
#define PCI_BAR(N)                            (PCI_BASE_ADDRESSREG_OFFSET+((N)<<2))
#define PCI_CLASS_BASE_MASS_STORAGE          0x01
#define PCI_CLASS_BASE_SERIAL_BUS            0x0C

typedef enum  __PCI_DEV_CLASS {
   PciDevSata = 1,
   PciDevNvme,
   PciDevUsb
}PCI_DEV_CLASS;

typedef struct {
  EFI_DEVICE_PATH_PROTOCOL      *DevicePath;
  UINTN                         DevicePathLength;
} PEI_PCI_DEVICE_PATH;

typedef struct {
  UINT8         Bus;
  UINT8         Dev;
  UINT8         Func;
  UINT16        Offset;//register addr
} EFI_PCI_REG;

typedef struct __EFI_PCI_BAR {
   UINT8   BarNum;
   UINTN   MmioBase;//only support 32bit address
   UINTN   BarSize;
}EFI_PCI_BAR;

typedef struct {
  EFI_PCI_REG   Addr;
#define HEADER_TYPE_INVALID_DEVICE  0xff
  UINT8         Type;/*1:bridge,0:device*/
  PCI_DEV_CLASS Class;
  EFI_PCI_BAR   Bar;//only support one bar
}EFI_PCI_DEVICE;

#define EFI_PCI_GROUP_SIGNATURE SIGNATURE_32 ('E', 'P', 'G', 'P')
typedef struct __EFI_PCI_GROUP__{
  UINT32             Signature;
  LIST_ENTRY         Link;
  EFI_PCI_DEVICE    *DevList;
  UINT16             DevCount;
  PEI_PCI_DEVICE_PATH   DevPath;
}EFI_PCI_GROUP;
#define EFI_PCI_GROUP_FROM_LINK(_link)  CR (_link, EFI_PCI_GROUP, Link, EFI_PCI_GROUP_SIGNATURE)
#define PCI_DEV_REG(pPciDev)  PCI_LIB_ADDRESS (pPciDev->Bus, pPciDev->Dev, pPciDev->Func, pPciDev->Offset)

typedef struct __DeviceConfigInfo{
  UINT64  SataBase;
  UINT64  SataLen;
  UINT64  SataPos;
  UINT64  NvmeBase;
  UINT64  NvmeLen;
  UINT64  NvmePos;
  //UINT64  UsbBase;
  //UINT64  UsbLen;
  //UINT64  UsbPos;
}DEVICE_CONFIG_INFO;

/**
  Get the pci device group by the Controllerid.

  @param[in]  pDevGroupList               The EFI_PCI_GROUP pointer.
  @param[in]  DevGroupCount               The pci device group count.
  @param[out] ControllerId              The controller device id.

  @retval pPciGroup               The pci device group pointer.
  @retval NULL                    The parameters are invalid.

**/

EFI_PCI_GROUP *
GetPciGroupById (
   IN  EFI_PCI_GROUP    *pDevGroupList,
   IN  UINT16           DevGroupCount,
   IN  UINT8            ControllerId
);

/**
  Get the MMIO base address of pci host controller.

  @param[in]  PciDev               The EFI_PCI_DEVICE pointer.
  @param[out] MmioBar              The MMIO base address of the controller.

  @retval EFI_SUCCESS              The operation succeeds.
  @retval EFI_INVALID_PARAMETER    The parameters are invalid.

**/
EFI_STATUS
EFIAPI
GetPciDevMmioBar (
  IN  EFI_PCI_DEVICE        *PeiDev,
  OUT UINTN                 *MmioBar
);

/**
  Get the device path of pci host controller.

  @param[in]  PciDevPath           The PEI_PCI_DEVICE_PATH pointer.
  @param[out] DevicePathLength     The length of the device path in bytes specified
                                   by DevicePath.
  @param[out] DevicePath           The device path of ATA AHCI host controller.
                                   This field re-uses EFI Device Path Protocol as
                                   defined by Section 10.2 EFI Device Path Protocol
                                   of UEFI 2.7 Specification.

  @retval EFI_SUCCESS              The operation succeeds.
  @retval EFI_INVALID_PARAMETER    The parameters are invalid.

**/
EFI_STATUS
EFIAPI
GetPciDevicePath (
  IN  PEI_PCI_DEVICE_PATH        *PciDevPath,
  OUT UINTN                      *DevicePathLength,
  OUT EFI_DEVICE_PATH_PROTOCOL   **DevicePath
);

EFI_STATUS
ParsePeiPciDevCfg(
  IN CONST CHAR8 * pDevCfg,
  IN UINT16    Length,
  OUT EFI_PCI_GROUP * pGroup
);

EFI_STATUS
FreeAllPciDevMem (
  IN VOID * Mem
);

EFI_STATUS
FreeAllPciDevicePathMem (
  VOID
);

/**
  @param[in]  DevClass       the pci device controller class.
  @param[in]  pDevGroupList   the EFI_PCI_GROUP pointer.
  @param[out]  pDevGroupCount   the pci device group count pointer

  @retval EFI_SUCCESS    init pci bus successfully
  @retval EFI_INVALID_PARAMETER    The parameters are invalid.

**/
EFI_STATUS
InitPciBus (
  IN  PCI_DEV_CLASS      DevClass,
  IN  OUT EFI_PCI_GROUP     *pDevGroupList,
  OUT UINT16            *pDevGroupCount
);


EFI_STATUS
S3UnlockHddMemPeiInit (
  VOID
);

#endif
